package io.coderyeah.basic.aspect;

import io.coderyeah.basic.annotation.LogAnnotation;
import io.coderyeah.org.domain.OperationLog;
import io.coderyeah.org.service.OperationLogService;
import io.coderyeah.basic.util.IpAddressUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Objects;

@Component
@Aspect //定义一个切面
@Slf4j
public class LogsAspect {
    @Autowired
    private OperationLogService logService;

    /**
     * 定义一个切点
     * 记录部门管理接口的所有日志
     * 使用@annotation时，所修饰的方法或是接口都会被拦截。
     * 使用execution时，指定你要切入的一个地方。
     */
    @Pointcut("@annotation(io.coderyeah.basic.annotation.LogAnnotation)")
    public void pointCut() {
    }


    /**
     * 环绕方法
     *
     * @param joinPoint 连接点
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行方法
        final Object result = joinPoint.proceed();
        // 日志记录
        record(joinPoint);
        return result;
    }

    /**
     * 记录日志
     *
     * @param joinPoint 连接点
     */
    private void record(ProceedingJoinPoint joinPoint) {
        final MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        final Method method = methodSignature.getMethod();
        final LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        //获取用户ip地址
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        log.info("====================记录日志开始====================");
        log.info("日志模块：{}", logAnnotation.module());
        log.info("日志操作：{}", logAnnotation.operate());
        log.info("请求方法：{}", joinPoint.getTarget().getClass().getName() + "." + methodSignature.getName() + "()");
        log.info("请求IP：{}", IpAddressUtils.getIpAddress2(request));
        // 保存日志
        String module = logAnnotation.module();
        String description = logAnnotation.operate();
        String ReqMethod = joinPoint.getTarget().getClass().getName() + "." + methodSignature.getName() + "()";
        String IP = IpAddressUtils.getIpAddress2(request);
        if (saveLog(module, description, ReqMethod, IP)) {
            log.info("====================保存日志成功====================");
        }
        log.info("====================记录日志结束====================");
    }

    private boolean saveLog(String module, String description, String reqMethod, String ip) {
        final OperationLog operationLog = new OperationLog();
        operationLog.setUsername("coderyeah");
        operationLog.setDescription(description);
        operationLog.setCreateTime(new Date());
        operationLog.setIp(ip);
        operationLog.setMethodName(reqMethod);
        operationLog.setModule(module);
        return logService.save(operationLog);
    }

}
